systemisches Beispiel rund um Uebergabestellen

Logging

[1]:
import os
import logging

logger = logging.getLogger()

logFileName= r"BWV.log"

loglevel = logging.DEBUG
logging.basicConfig(filename=logFileName
                        ,filemode='w'
                        ,level=loglevel
                        ,format="%(asctime)s ; %(name)-60s ; %(levelname)-7s ; %(message)s")

fileHandler = logging.FileHandler(logFileName)

logger.addHandler(fileHandler)

consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(logging.Formatter("%(levelname)-7s ; %(message)s"))

consoleHandler.setLevel(logging.INFO) # ggf. DEBUG/WARNING/ERROR
logger.addHandler(consoleHandler)

import pandas as pd
import geopandas as gpd
import networkx as nx
import glob
import re
import numpy as np
import folium
from folium.plugins import HeatMap
import doctest
INFO    ; Note: NumExpr detected 12 cores but "NUMEXPR_MAX_THREADS" not set, so enforcing safe limit of 8.
INFO    ; NumExpr defaulting to 8 threads.

Modelldatei

[2]:
dbFilename="BWV"

PT3S (Python Module für SIR 3S’ MX und SIR 3S’ DB)

nachfolgende Zeile mit # deaktivieren wenn aktuelle Version bereits installiert oder kein Update gewünscht

[3]:
!pip install PT3S -U --no-deps
Requirement already satisfied: PT3S in c:\users\wolters\appdata\local\anaconda3\lib\site-packages (90.14.15.0.dev1)
[4]:
try:
    from PT3S import dxAndMxHelperFcts
except:
    import dxAndMxHelperFcts

Modell und Ergebnisse lesen

[5]:
m=dxAndMxHelperFcts.readDxAndMx(dbFile=os.path.join('.',dbFilename+'.db3')
                               #,forceSir3sRead=True
                               #,preventPklDump=True
                               )
INFO    ; PT3S.dxAndMxHelperFcts.readDxAndMx: .\BWV-dx.pkl newer than dbFile and therefore read ...
INFO    ; PT3S.dxAndMxHelperFcts.readDxAndMx: .\BWV-mx-WDBWV_B1_V0_BZ1_M_1_0_1_1_MX1.pkl newer than mxFile and therefore read ...
INFO    ; PT3S.dxAndMxHelperFcts.readDxAndMx: .\BWV-m.pkl exists newer than M-1-0-1.1.MX1 and is therefore read ...

Shapes

lesen

[6]:
shapes={}
for shpFile in glob.glob(r".\GIS Daten\*.shp"):

    gdf=gpd.read_file(shpFile)

    shpFilename=os.path.basename(shpFile)
    shpFilename,tail=os.path.splitext(shpFilename)
    shapes[shpFilename]=gdf

    print("{:s}: Objekte: {:d} Attribute: {:d}:".format(shpFilename,gdf.shape[0],gdf.shape[1]))
    print(sorted(gdf.columns.to_list()))
AA_T_B_BAUTEIL: Objekte: 9654 Attribute: 20:
['ANLAGENID_', 'ARMATURSTE', 'EIGENSCHAF', 'EINGEARBEI', 'FUNKTION_B', 'HOEHENIND1', 'HOEHENIND2', 'HOEHENINDE', 'H_SYSTEM_1', 'H_SYSTEM_R', 'H_SYSTEM_U', 'LEITUNGSNR', 'PK', 'RNB_RELEVA', 'ROK', 'ROK_ABGEHE', 'STATUS', 'UEBEREICHH', 'UEBERGABES', 'geometry']
AA_T_B_LEITUNGSABSCHNITT_ALL: Objekte: 10070 Attribute: 17:
['ABSCHNITTS', 'ANLASS_VER', 'BETRIEBSST', 'DATUM_INBE', 'DN', 'GRUND_VERL', 'KATEGORIE', 'LAGEINDEX', 'LEITUNGSNR', 'MATERIAL', 'NENNDRUCKS', 'PK', 'PUMPENDRUC', 'RNB_RELEVA', 'STATUS', 'geometry', 'pk_string']
B_UEBERGABESTELLE: Objekte: 452 Attribute: 16:
['BEMERKUNG', 'FUNKTION_B', 'MIS_BEHAEL', 'MIS_BENUTZ', 'MIS_BWVWAS', 'MIS_EIGENW', 'MIS_MISCHW', 'MIS_UGSTBE', 'MIS_UGSTID', 'MIS_UGSTN1', 'MIS_UGSTN2', 'MIS_UGSTNA', 'MITGLIEDSN', 'PK', 'STATUS', 'geometry']

sichten

[7]:
shpFilenameLeitungen=[key for key in shapes.keys() if re.search('LEITUNGSABSCHNITT',key) != None][0]
shpLeitungen=shapes[shpFilenameLeitungen]
[8]:
shpLeitungen['DN'].describe()
[8]:
count    10070.000000
mean       468.969712
std        399.662788
min          0.000000
25%        150.000000
50%        300.000000
75%        600.000000
max       3300.000000
Name: DN, dtype: float64
[9]:
shpLeitungen.crs
[9]:
<Projected CRS: PROJCS["Potsdam_3_Degree_GK_Zone_3",GEOGCS["GCS_Po ...>
Name: Potsdam_3_Degree_GK_Zone_3
Axis Info [cartesian]:
- [east]: Easting (metre)
- [north]: Northing (metre)
Area of Use:
- undefined
Coordinate Operation:
- name: unnamed
- method: Transverse Mercator
Datum: Deutsches_Hauptdreiecksnetz
- Ellipsoid: Bessel 1841
- Prime Meridian: Greenwich
[10]:
minWidthinPixel=.75
maxWidthinPixel=5*minWidthinPixel
facWidthinPixelDN=1/200.

mLtg=shpLeitungen[~pd.isnull(shpLeitungen['geometry'])].sort_values(by=['DN'],ascending=True).explore(column='DN'
        ,cmap='cool_r',vmin=shpLeitungen['DN'].quantile(.20),vmax=shpLeitungen['DN'].quantile(.80)
        ,style_kwds={"style_function":lambda x: {"weight":min(max(x["properties"]["DN"]*facWidthinPixelDN,minWidthinPixel),maxWidthinPixel)}}
        ,tiles='CartoDB Positron' #'OpenStreetMap'
        ,name='shpLeitungen'
)
[1]:
mLtg
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[1], line 1
----> 1 mLtg

NameError: name 'mLtg' is not defined
[12]:
shpFilenameUebergabestellen=[key for key in shapes.keys() if re.search('UEBERGABESTELLE',key) != None][0]
shpUebergabestellen=shapes[shpFilenameUebergabestellen]
[13]:
shpUebergabestellen.describe()
[13]:
MIS_UGSTID MIS_BWVWAS MIS_EIGENW MIS_BEHAEL PK
count 452.000000 84.000000 84.000000 399.000000 452.000000
mean 839.000000 51.909524 48.028571 1814.030075 6995.389381
std 819.492677 16.515933 16.520608 3364.607982 4495.498042
min 1.000000 12.000000 0.000000 1.000000 170.000000
25% 125.750000 42.750000 39.750000 387.500000 5110.750000
50% 1064.500000 50.000000 50.000000 850.000000 5261.500000
75% 1184.250000 60.250000 57.250000 2000.000000 5453.000000
max 7003.000000 100.000000 88.000000 32990.000000 23191.000000
[14]:
shpUebergabestellen[pd.isnull(shpUebergabestellen['MIS_BEHAEL'])].describe()
[14]:
MIS_UGSTID MIS_BWVWAS MIS_EIGENW MIS_BEHAEL PK
count 53.000000 1.0 1.0 0.0 53.000000
mean 1449.603774 50.0 50.0 NaN 10442.886792
std 1626.053875 NaN NaN NaN 6505.304113
min 10.000000 50.0 50.0 NaN 179.000000
25% 1038.000000 50.0 50.0 NaN 5230.000000
50% 1154.000000 50.0 50.0 NaN 5501.000000
75% 1272.000000 50.0 50.0 NaN 14794.000000
max 7003.000000 50.0 50.0 NaN 22568.000000
[15]:
gdfUe1=shpUebergabestellen[
(~pd.isnull(shpUebergabestellen['geometry']))
&
(~shpUebergabestellen['MIS_BEHAEL'].isin([0.,None,np.nan]))
]

gdfUe1["MIS_BEHAEL"].describe()
[15]:
count      399.000000
mean      1814.030075
std       3364.607982
min          1.000000
25%        387.500000
50%        850.000000
75%       2000.000000
max      32990.000000
Name: MIS_BEHAEL, dtype: float64
[16]:

minRadius=2 maxRadius=10*minRadius facRadius=1/1000. mUe=gdfUe1.sort_values(by=['MIS_BEHAEL'],ascending=False).explode().explore(column='MIS_BEHAEL' ,cmap='autumn_r' ,vmin=gdfUe1["MIS_BEHAEL"].quantile(.025),vmax=gdfUe1["MIS_BEHAEL"].quantile(.975) ,style_kwds={"style_function":lambda x: { "radius":min(max(x["properties"]["MIS_BEHAEL"]*facRadius,minRadius),maxRadius) } } ,tiles='CartoDB Positron' #'OpenStreetMap' ,name='shpUebergabestellen' )
[17]:
mUe
[17]:
Make this Notebook Trusted to load map: File -> Trust Notebook
[18]:
dfLonLat=gdfUe1.to_crs("EPSG:4326").geometry.get_coordinates()
dfLonLat.head()
[18]:
x y
0 8.902281 48.761125
1 8.840359 47.968704
2 9.295282 49.619030
3 9.006094 48.732733
4 8.959045 48.703604
[19]:
dfLonLatValue=pd.merge(gdfUe1,dfLonLat,left_index=True,right_index=True)[['x','y','MIS_BEHAEL']]
dfLonLatValue.head()
[19]:
x y MIS_BEHAEL
0 8.902281 48.761125 2000.0
1 8.840359 47.968704 400.0
2 9.295282 49.619030 300.0
3 9.006094 48.732733 600.0
4 8.959045 48.703604 500.0
[20]:
dfLonLatValue['xW']=dfLonLatValue.apply(lambda row: row['x']*row['MIS_BEHAEL'],axis=1)
dfLonLatValue['yW']=dfLonLatValue.apply(lambda row: row['y']*row['MIS_BEHAEL'],axis=1)
[21]:
dfLonLatValue.mean()
[21]:
x                 9.079953
y                48.871738
MIS_BEHAEL     1814.030075
xW            16493.425336
yW            88504.866735
dtype: float64
[22]:
xAvgW=dfLonLatValue['xW'].sum()/dfLonLatValue['MIS_BEHAEL'].sum()
yAvgW=dfLonLatValue['yW'].sum()/dfLonLatValue['MIS_BEHAEL'].sum()
xAvgW,yAvgW
[22]:
(9.092145473005848, 48.78908456141424)
[23]:
heatMapData = [[row['y'],row['x'],row['MIS_BEHAEL']] for index, row in dfLonLatValue.iterrows()]
[24]:
heatMapData[:3]
[24]:
[[48.761125384297436, 8.902280702401265, 2000.0],
 [47.968704067404566, 8.840358974788511, 400.0],
 [49.61903026968014, 9.29528199847166, 300.0]]
[25]:
map = folium.Map(location=(yAvgW,xAvgW)
               ,tiles='CartoDB Positron' #'OpenStreetMap'
               ,zoom_start=11
              )
HeatMap(heatMapData,name='Heat Map von MIS_BEHAEL Radius 10 Größe 5',radius=10,blur=5,base=True).add_to(map)
[25]:
<folium.plugins.heat_map.HeatMap at 0x1c7894c9cd0>
[26]:

shpLeitungen[~pd.isnull(shpLeitungen['geometry'])].sort_values(by=['DN'],ascending=True).explore(column='DN' ,cmap='cool_r',vmin=shpLeitungen['DN'].quantile(.20),vmax=shpLeitungen['DN'].quantile(.80) #,legend=False ,style_kwds={"style_function":lambda x: {"weight":min(max(x["properties"]["DN"]*facWidthinPixelDN,minWidthinPixel),maxWidthinPixel)}} #,tiles='CartoDB Positron' #'OpenStreetMap' ,name='shpLeitungen' ,m=map ) gdfUe1[['MITGLIEDSN','MIS_UGSTID','MIS_BEHAEL','geometry']].explode().sort_values(by=['MIS_BEHAEL'],ascending=False).explore(column='MIS_BEHAEL' ,cmap='autumn_r',vmin=gdfUe1["MIS_BEHAEL"].quantile(.025),vmax=gdfUe1["MIS_BEHAEL"].quantile(.975) #,legend=False ,style_kwds={"style_function":lambda x: {"radius":min(max(x["properties"]["MIS_BEHAEL"]*facRadius,minRadius),maxRadius)}} #,tiles='CartoDB Positron' #'OpenStreetMap' ,name='shpUebergabestellen' ,m=map ) dummy=folium.LayerControl().add_to(map)

=== Kartenbeispiel

[27]:
map
[27]:
Make this Notebook Trusted to load map: File -> Trust Notebook

LF

lesen

[28]:
df=pd.read_excel('Eingangsdaten_BWV.xlsx',header=1)
df.head()
[28]:
UGSTID BQ-Quote [l/s] BQ-Quote [l/s].1
0 1122 18.333333 18.333333
1 1123 6.333333 6.333333
2 1124 14.333333 14.333333
3 1125 24.733333 24.733333
4 1126 13.866667 13.866667
[29]:
df.rename(columns=
{col:"LF {:d}".format(idx+1) for idx,col in
enumerate([col for col in df.columns.to_list() if re.search('^BQ',col)])}
,inplace=True)
df.head()
[29]:
UGSTID LF 1 LF 2
0 1122 18.333333 18.333333
1 1123 6.333333 6.333333
2 1124 14.333333 14.333333
3 1125 24.733333 24.733333
4 1126 13.866667 13.866667

Mapping zu Modellknoten

[30]:
modellKnotenNamen=sorted([name for name in m.dx.dataFrames['KNOT']['NAME'].values if name not in [None]])
[31]:
modellKnotenNamen[:3],modellKnotenNamen[-3:]
[31]:
(['12713', '19369_k', '19857_k'], ['xW9990i1279', 'xW9990k', 'xk26461_E136'])
[32]:
'xW5428i1122' in modellKnotenNamen
[32]:
True
[33]:
UGSTID2Name=[]

for index, row in df.iterrows():
    pass
    #print(row)
    reExpStr='(?P<UGSTID>{:d})$'.format(int(row['UGSTID']))
    #print(reExpStr)
    matches=[]
    for name in modellKnotenNamen:
        #print(name)

        #if name=='xW5428i1122':
        #    print(name)



        mo=re.search(reExpStr,name)
        if mo != None:
            matches.append(name)
    UGSTID2Name.append(matches)
[34]:
df['UGSTID2Name']=UGSTID2Name
[35]:
df['UGSTID2NameFinal']=df['UGSTID2Name'].apply(lambda x: x[-1] if x != None else None)
[36]:
df.head()
[36]:
UGSTID LF 1 LF 2 UGSTID2Name UGSTID2NameFinal
0 1122 18.333333 18.333333 [W5428k1122, xW5428i1122] xW5428i1122
1 1123 6.333333 6.333333 [W5427k1123, xW5427i1123] xW5427i1123
2 1124 14.333333 14.333333 [W5071k1124, xW5071i1124] xW5071i1124
3 1125 24.733333 24.733333 [W5070k1125, xW5070i1125] xW5070i1125
4 1126 13.866667 13.866667 [W7646k1126, xW7646i1126] xW7646i1126

aktuelles stat. Berechnungergebnis zu Information

[37]:
t0=pd.Timestamp(m.mx.df.index[0].strftime('%Y-%m-%d %X.%f'))
[38]:
QM=('STAT',
  'KNOT~*~*~*~QM',
  t0,
  t0)
[39]:
m.V3_KNOT['QM stat.']=m.V3_KNOT[QM]
[40]:
dfMatch=pd.merge(df,m.V3_KNOT,left_on='UGSTID2NameFinal',right_on='NAME',how='left')
[41]:
def testMatchKNOT():
    '''
    >>> df.shape[0]==dfMatch.shape[0]
    True
    >>> dfMatch[pd.isnull(dfMatch['NAME'])].shape[0]==0
    True
    '''
import doctest
doctest.testmod()
[41]:
TestResults(failed=0, attempted=2)
[42]:
#sorted([col for col in dfMatch.columns.to_list() if not  isinstance(col,tuple)])
[43]:
# 'NAME_QVAR'
[44]:
dfMatch=dfMatch.filter(items=df.columns.to_list()+['QM stat.','NAME_QVAR',
'fkQVAR',
 'XKOR',
 'YKOR'
])
[45]:
dfMatch.head()
[45]:
UGSTID LF 1 LF 2 UGSTID2Name UGSTID2NameFinal QM stat. NAME_QVAR fkQVAR XKOR YKOR
0 1122 18.333333 18.333333 [W5428k1122, xW5428i1122] xW5428i1122 -27.5 W5428i1122t 5596220771254152013 3501258.51 5395931.71
1 1123 6.333333 6.333333 [W5427k1123, xW5427i1123] xW5427i1123 -9.5 W5427i1123t 5323895754976366882 3501316.54 5395978.55
2 1124 14.333333 14.333333 [W5071k1124, xW5071i1124] xW5071i1124 -21.5 W5071i1124t 4718577275119368741 3501755.57 5397652.25
3 1125 24.733333 24.733333 [W5070k1125, xW5070i1125] xW5070i1125 -37.099998 W5070i1125t 4667019898132438953 3501747.47 5397717.92
4 1126 13.866667 13.866667 [W7646k1126, xW7646i1126] xW7646i1126 -20.799999 W7646i1126t 4757386671245806602 3500525.66 5399415.61
[46]:
dfMatchColsSoFar=dfMatch.columns.to_list()

Mapping zu Sollwerttabellen

[47]:
dfQVAR=m.dx.dataFrames['V_BVZ_QVAR']
[48]:
dfMatch=pd.merge(dfMatch
         ,dfQVAR[dfQVAR['lfdNrZEIT']==1]
         ,left_on='fkQVAR',right_on='pk',how='left'
         ,suffixes=('','_QVAR')
)
[49]:
def testMatchQVAR():
    '''
    >>> df.shape[0]==dfMatch.shape[0]
    True
    >>> dfMatch[pd.isnull(dfMatch['NAME'])].shape[0]==0
    True
    '''
import doctest
doctest.testmod()
[49]:
TestResults(failed=0, attempted=4)
[50]:
dfMatch=dfMatch.filter(items=dfMatchColsSoFar+['QM','pk_BZ','BESCHREIBUNG'
])
dfMatch.head()
[50]:
UGSTID LF 1 LF 2 UGSTID2Name UGSTID2NameFinal QM stat. NAME_QVAR fkQVAR XKOR YKOR QM pk_BZ BESCHREIBUNG
0 1122 18.333333 18.333333 [W5428k1122, xW5428i1122] xW5428i1122 -27.5 W5428i1122t 5596220771254152013 3501258.51 5395931.71 18.333333 4856987974013881829 ++Ü1122# SIFI# MitglNR 119000
1 1123 6.333333 6.333333 [W5427k1123, xW5427i1123] xW5427i1123 -9.5 W5427i1123t 5323895754976366882 3501316.54 5395978.55 6.333333 5663416766907617621 ++Ü1123# SIFI# MitglNR 119000
2 1124 14.333333 14.333333 [W5071k1124, xW5071i1124] xW5071i1124 -21.5 W5071i1124t 4718577275119368741 3501755.57 5397652.25 14.333333 4886541335056741938 ++Ü1124# SIFI# MitglNR 119000
3 1125 24.733333 24.733333 [W5070k1125, xW5070i1125] xW5070i1125 -37.099998 W5070i1125t 4667019898132438953 3501747.47 5397717.92 24.733333 4828834850543938057 ++Ü1125# SIFI# MitglNR 119000
4 1126 13.866667 13.866667 [W7646k1126, xW7646i1126] xW7646i1126 -20.799999 W7646i1126t 4757386671245806602 3500525.66 5399415.61 13.866667 5347726789982458032 ++Ü1126# SIFI# MitglNR 119000

LF in Modell uebernehmen

per Datenbankzugriff

[51]:
# Prinzip: Objekttyp (Tabelle), Attribut das geändert werden soll (hier Spalte QM), der Wert auf den das Attribut gesetzt werden soll (hier LF 1), Schluesseldaten
dfMatch['table']='QVAR_ROWT'
dfMatch['attrib']='QM'
dfMatch['attribValue']=dfMatch['LF 1'] # 'LF 2'
dfMatch['xk']='pk'
dfMatch['xkValue']=dfMatch['pk_BZ']
[52]:
m.dx.update(dfMatch)

per Prozessdatenimportdatei generieren

[53]:
dfMatch['NAME']=dfMatch['NAME_QVAR']
dfMatch['TAG']=m.mx.df.index[0].strftime('%d.%m.%Y')
dfMatch['UHRZEIT']=m.mx.df.index[0].strftime('%H:%M')#:%S')
dfMatch['WERT']=-dfMatch['LF 1'] # 'LF 2'
dfMatch['PLS_ID']=dfMatch.apply(lambda row: "{!s:s} - ber. Wert IST: {:6.2f}".format(row['UGSTID'],row['QM stat.']),axis=1)
[54]:
#dfMatch.head()
[55]:
dfMatch[['NAME','TAG','UHRZEIT','WERT','BESCHREIBUNG','PLS_ID']].head()
[55]:
NAME TAG UHRZEIT WERT BESCHREIBUNG PLS_ID
0 W5428i1122t 26.06.2023 08:00 -18.333333 ++Ü1122# SIFI# MitglNR 119000 1122 - ber. Wert IST: -27.50
1 W5427i1123t 26.06.2023 08:00 -6.333333 ++Ü1123# SIFI# MitglNR 119000 1123 - ber. Wert IST: -9.50
2 W5071i1124t 26.06.2023 08:00 -14.333333 ++Ü1124# SIFI# MitglNR 119000 1124 - ber. Wert IST: -21.50
3 W5070i1125t 26.06.2023 08:00 -24.733333 ++Ü1125# SIFI# MitglNR 119000 1125 - ber. Wert IST: -37.10
4 W7646i1126t 26.06.2023 08:00 -13.866667 ++Ü1126# SIFI# MitglNR 119000 1126 - ber. Wert IST: -20.80
[56]:
dfMatch[['NAME','TAG','UHRZEIT','WERT','BESCHREIBUNG','PLS_ID']].sort_values(by=['PLS_ID']).to_csv('LF1 Prozessdatenimport.csv',sep=';',index=False)

Prozessdatenimportdatei für alle LFs

[57]:
dfs=[]
timestep=pd.Timedelta('3 Minutes')
for idx,lfCol in enumerate([col for col in dfMatch.columns.to_list() if re.search('^LF \d+',col)]):
    t=m.mx.df.index[0]+(idx+1)*timestep
    dfMatch['WERT']=-dfMatch[lfCol]
    dfMatch['UHRZEIT']=t.strftime('%H:%M')#:%S')
    dfMatch['PLS_ID']=dfMatch.apply(lambda row: "{!s:s} - {:s} auf Zeitschritt {:d}".format(row['UGSTID'],lfCol,idx+1),axis=1)

    dfs.append(dfMatch[['NAME','TAG','UHRZEIT','WERT','BESCHREIBUNG','PLS_ID']])

Ist-Ergebnis als 1. Zeit ergänzen

[58]:
dfMatch['UHRZEIT']=m.mx.df.index[0].strftime('%H:%M')#:%S')
dfMatch['WERT']=dfMatch['QM stat.']
dfMatch['PLS_ID']=dfMatch.apply(lambda row: "{!s:s} - ber. Wert IST auf Zeitschritt 0".format(row['UGSTID']),axis=1)
dfs.append(dfMatch[['NAME','TAG','UHRZEIT','WERT','BESCHREIBUNG','PLS_ID']])
[59]:
pd.concat(dfs).sort_values(by=['NAME','UHRZEIT']).to_csv('LF alle Prozessdatenimport.csv',sep=';',index=False)

Anmerkungen zu anderen Möglichkeiten aus der E-Mail

es ist moeglich die SirCalc Xml des Basismodells zu verwenden und diese zu skripten und pro LF eine Xml zu erzeugen und diese per Skript automatisiert rechnen zu lassen und die Ergebnisse im Skript wieder “einzusammeln” fuer Vergleiche; effizienter erscheint es hier die gewünschten BQ-LF-Kombis als quasi-stat. Rechnungen aufzufassen und in 1 Modell zu halten und geschlossen zu berechnen; die Mail nennt dies ja ebenfalls als Alternative

Bsp. Modellergebnisse in Karte

[60]:
crs=gdfUe1.crs
[61]:
gs=gpd.GeoSeries.from_wkb(m.V3_KNOT['GEOMWKB'],crs=crs)
gdf_KNOT=gpd.GeoDataFrame(m.V3_KNOT,geometry=gs,crs=crs)
[62]:
#gdf_KNOT['NAME_QVAR'].unique()
[63]:
#gdf_KNOT.columns.to_list()
[64]:
#gdf_KNOT[
#    ~(pd.isnull(gdf_KNOT.geometry))
#]['NAME_QVAR'].unique()#[['NAME_QVAR','NAME','QM stat.']]
[65]:
gdf_KNOTUe=gdf_KNOT[
    ~(pd.isnull(gdf_KNOT.geometry))
    &
    ~(gdf_KNOT['NAME_QVAR'].isin([None,np.nan]))
    &
    (gdf_KNOT.ID_CONT==gdf_KNOT.IDPARENT_CONT)
][['geometry','NAME_QVAR','NAME','QM stat.']]
gdf_KNOTUe.head()
[65]:
geometry NAME_QVAR NAME QM stat.
55 POINT (3479977.948 5446804.237) W5315i18t xW5315i18 -1.2
63 POINT (3497945.584 5422049.559) W5440i154t xW5440i154 -6.1
73 POINT (3506033.959 5399040.544) W5087i1146t xW5087i1146 -200.970001
117 POINT (3499501.980 5398326.649) W20265i5048t W20265i5048 0.0
125 POINT (3502646.044 5411566.676) W5110i1029t xW5110i1029 -11.0
[66]:
gdf_KNOTUe['UGSTID']=gdf_KNOTUe['NAME'].apply(lambda x: int(re.search("(?P<UGSTID>\d+)$",x).group('UGSTID')) if re.search("(?P<UGSTID>\d+)$",x)!=None else None)
[67]:
gdf_KNOTUe.head()
[67]:
geometry NAME_QVAR NAME QM stat. UGSTID
55 POINT (3479977.948 5446804.237) W5315i18t xW5315i18 -1.2 18.0
63 POINT (3497945.584 5422049.559) W5440i154t xW5440i154 -6.1 154.0
73 POINT (3506033.959 5399040.544) W5087i1146t xW5087i1146 -200.970001 1146.0
117 POINT (3499501.980 5398326.649) W20265i5048t W20265i5048 0.0 5048.0
125 POINT (3502646.044 5411566.676) W5110i1029t xW5110i1029 -11.0 1029.0
[68]:
gdf_KNOTUe.shape
[68]:
(453, 5)
[69]:
gdf_KNOTUe=pd.merge(gdf_KNOTUe,shpUebergabestellen,left_on='UGSTID',right_on='MIS_UGSTID',how='left',suffixes=('','_shp')).filter(items=gdf_KNOTUe.columns.to_list()+['MITGLIEDSN','MIS_UGSTNA','geometry_shp'])
gdf_KNOTUe.head()
[69]:
geometry NAME_QVAR NAME QM stat. UGSTID MITGLIEDSN MIS_UGSTNA geometry_shp
0 POINT (3479977.948 5446804.237) W5315i18t xW5315i18 -1.2 18.0 Kraichtal HB Neuenbürg MULTIPOINT (3479992.445 5446754.523)
1 POINT (3497945.584 5422049.559) W5440i154t xW5440i154 -6.1 154.0 Vaihingen/Enz HB Vaihingen-Wolfshalde2 Süd MULTIPOINT (3497877.327 5422071.783)
2 POINT (3506033.959 5399040.544) W5087i1146t xW5087i1146 -200.970001 1146.0 Netze BW Wasser GmbH HB Vaihingen (Ltg 1) MULTIPOINT (3506084.904 5399016.093)
3 POINT (3499501.980 5398326.649) W20265i5048t W20265i5048 0.0 5048.0 Sindelfingen HB Sifi Eichholz-IBM Z2 MULTIPOINT (3499551.980 5398326.649)
4 POINT (3502646.044 5411566.676) W5110i1029t xW5110i1029 -11.0 1029.0 Ditzingen HB Hirschlanden MULTIPOINT (3502651.669 5411516.994)
[70]:
gdf_KNOTUe.shape
[70]:
(454, 8)
[71]:
# Ue im Modell ohne Referenz im Shape
gdf_KNOTUe[pd.isnull(gdf_KNOTUe['geometry_shp'])]
[71]:
geometry NAME_QVAR NAME QM stat. UGSTID MITGLIEDSN MIS_UGSTNA geometry_shp
17 POINT (3503507.196 5300049.134) W5429i1176t xW5429i1176 0.0 1176.0 NaN NaN None
27 POINT (3482819.301 5440615.952) W5311i17t xW5311i17 0.0 17.0 NaN NaN None
104 POINT (3480864.767 5420005.310) W9945it xW9945i -25.0 NaN NaN NaN None
125 POINT (3478822.217 5440396.413) W9960it xW9960i -7.1 NaN NaN NaN None
129 POINT (3484346.194 5423912.672) W9955it xW9955i 0.0 NaN NaN NaN None
154 POINT (3509699.132 5443104.941) W9910it xW9910i 0.0 NaN NaN NaN None
179 POINT (3493130.913 5437828.439) W9980it xW9980i -5.0 NaN NaN NaN None
224 POINT (3523271.002 5478648.177) W8567i183t xW8567i183 0.0 183.0 NaN NaN None
284 POINT (3527604.815 5387711.596) W12132i1093t xW12132i1093 0.0 1093.0 NaN NaN None
298 POINT (3508514.906 5431411.979) W9920it xW9920i -3.0 NaN NaN NaN None
340 POINT (3504763.781 5405940.927) W14317i5016t xW14317i5016 0.0 5016.0 NaN NaN None
361 POINT (3505393.162 5405354.819) W14316i5017t xW14316i5017 0.0 5017.0 NaN NaN None
403 POINT (3506035.968 5405382.884) W14651i1150t xW14651i1150 -4.79 1150.0 NaN NaN None
[72]:
gdf_KNOTUe=gdf_KNOTUe[~pd.isnull(gdf_KNOTUe['geometry_shp'])]
[73]:
gdf_KNOTUe.shape
[73]:
(441, 8)
[74]:
gdf_KNOTUe=pd.merge(gdf_KNOTUe,gdf_KNOTUe.groupby(by=['UGSTID']).count()[['NAME']],left_on='UGSTID',right_index=True,suffixes=('','_group')).rename(columns={'NAME_group':'AnzMatches'})
[75]:
gdf_KNOTUe.shape
[75]:
(441, 9)
[76]:
# Ue im Modell mit mehr als 1 Referenz im Shape
gdf_KNOTUe[gdf_KNOTUe['AnzMatches']>1]
[76]:
geometry NAME_QVAR NAME QM stat. UGSTID MITGLIEDSN MIS_UGSTNA geometry_shp AnzMatches
31 POINT (3528469.541 5387284.309) W4993i1096t xW4993i1096 -7.34 1096.0 Nürtingen, Stadtwerke GmbH HB Reudern MULTIPOINT (3528431.841 5387317.153) 2
32 POINT (3528469.541 5387284.309) W4993i1096t xW4993i1096 -7.34 1096.0 Nürtingen, Stadtwerke GmbH HB Reudern MULTIPOINT (3528431.841 5387317.153) 2
52 POINT (3507906.945 5295489.748) K8124E116t K8124E116 -2.883 116.0 Rosenberg HB Hirschlanden MULTIPOINT (3536768.144 5481248.502) 2
317 POINT (3536723.222 5481270.459) W5227i116t xW5227i116 -0.8 116.0 Rosenberg HB Hirschlanden MULTIPOINT (3536768.144 5481248.502) 2
[77]:
gdf_KNOTUe=gdf_KNOTUe[gdf_KNOTUe['AnzMatches']==1].reset_index(drop=True)
[78]:
gdf_KNOTUe['geometry_shp']=gdf_KNOTUe['geometry_shp'].explode().reset_index()['geometry_shp']
[79]:
gdf_KNOTUe.head()
[79]:
geometry NAME_QVAR NAME QM stat. UGSTID MITGLIEDSN MIS_UGSTNA geometry_shp AnzMatches
0 POINT (3479977.948 5446804.237) W5315i18t xW5315i18 -1.2 18.0 Kraichtal HB Neuenbürg POINT (3479992.445 5446754.523) 1
1 POINT (3497945.584 5422049.559) W5440i154t xW5440i154 -6.1 154.0 Vaihingen/Enz HB Vaihingen-Wolfshalde2 Süd POINT (3497877.327 5422071.783) 1
2 POINT (3506033.959 5399040.544) W5087i1146t xW5087i1146 -200.970001 1146.0 Netze BW Wasser GmbH HB Vaihingen (Ltg 1) POINT (3506084.904 5399016.093) 1
3 POINT (3499501.980 5398326.649) W20265i5048t W20265i5048 0.0 5048.0 Sindelfingen HB Sifi Eichholz-IBM Z2 POINT (3499551.980 5398326.649) 1
4 POINT (3502646.044 5411566.676) W5110i1029t xW5110i1029 -11.0 1029.0 Ditzingen HB Hirschlanden POINT (3502651.669 5411516.994) 1
[80]:
gdf_KNOTUe['Abstand Shp Zu Sir3s']=gdf_KNOTUe['geometry_shp'].distance(gdf_KNOTUe['geometry'])
[81]:
gdf_KNOTUe.head()
[81]:
geometry NAME_QVAR NAME QM stat. UGSTID MITGLIEDSN MIS_UGSTNA geometry_shp AnzMatches Abstand Shp Zu Sir3s
0 POINT (3479977.948 5446804.237) W5315i18t xW5315i18 -1.2 18.0 Kraichtal HB Neuenbürg POINT (3479992.445 5446754.523) 1 51.783991
1 POINT (3497945.584 5422049.559) W5440i154t xW5440i154 -6.1 154.0 Vaihingen/Enz HB Vaihingen-Wolfshalde2 Süd POINT (3497877.327 5422071.783) 1 71.784095
2 POINT (3506033.959 5399040.544) W5087i1146t xW5087i1146 -200.970001 1146.0 Netze BW Wasser GmbH HB Vaihingen (Ltg 1) POINT (3506084.904 5399016.093) 1 56.508756
3 POINT (3499501.980 5398326.649) W20265i5048t W20265i5048 0.0 5048.0 Sindelfingen HB Sifi Eichholz-IBM Z2 POINT (3499551.980 5398326.649) 1 50.000000
4 POINT (3502646.044 5411566.676) W5110i1029t xW5110i1029 -11.0 1029.0 Ditzingen HB Hirschlanden POINT (3502651.669 5411516.994) 1 50.000000
[82]:
gdf_KNOTUe["QM stat."]=-gdf_KNOTUe["QM stat."].astype(float)
[83]:
gdf_KNOTUe["QM stat."].describe()
[83]:
count    437.000000
mean      17.105927
std       33.915411
min       -0.000000
25%        2.000000
50%        6.816000
75%       16.100000
max      264.769989
Name: QM stat., dtype: float64
[84]:
(fmin,fmax)=gdfUe1["MIS_BEHAEL"].quantile(.025)/gdf_KNOTUe["QM stat."].quantile(.075),gdfUe1["MIS_BEHAEL"].quantile(.975)/gdf_KNOTUe["QM stat."].quantile(.975)

(fmin,fmax)
# facRaduis
[84]:
(65.83333071735183, 89.87552351076495)
[85]:
gdf_KNOTUe[['NAME','UGSTID','MITGLIEDSN','MIS_UGSTNA','Abstand Shp Zu Sir3s','QM stat.','geometry']].sort_values(by=['QM stat.'],ascending=True).explore(column='QM stat.'
      ,cmap='autumn_r',vmin=gdf_KNOTUe["QM stat."].quantile(.075),vmax=gdf_KNOTUe["QM stat."].quantile(.975)
     ,legend=False
      ,style_kwds={"style_function":lambda x: {"radius":min(max(x["properties"]["QM stat."]*facRadius*max((fmin,fmax)),minRadius),maxRadius)}}
     ,tiles='CartoDB Positron' #'OpenStreetMap'
      ,name='QM stat.'
    #  ,m=map
)
[85]:
Make this Notebook Trusted to load map: File -> Trust Notebook
[86]:
dfLonLat=gdf_KNOTUe.to_crs("EPSG:4326").geometry.get_coordinates()
dfLonLat.head()
[86]:
x y
0 8.724467 49.158080
1 8.970929 48.935811
2 9.080989 48.728883
3 8.992202 48.722492
4 9.035018 48.841545
[87]:
dfLonLatValue=pd.merge(gdf_KNOTUe,dfLonLat,left_index=True,right_index=True)[['x','y','QM stat.']]
dfLonLatValue.head()
[87]:
x y QM stat.
0 8.724467 49.158080 1.200000
1 8.970929 48.935811 6.100000
2 9.080989 48.728883 200.970001
3 8.992202 48.722492 -0.000000
4 9.035018 48.841545 11.000000
[88]:
heatMapDataQMstat = [[row['y'],row['x'],row['QM stat.']] for index, row in dfLonLatValue.iterrows()]
[ ]:

[89]:
map = folium.Map(location=(yAvgW,xAvgW)
               ,tiles='CartoDB Positron' #'OpenStreetMap'
               ,zoom_start=11
              )

HeatMap(heatMapData,name='Heat Map von MIS_BEHAEL Radius 10 Größe 5',radius=10,blur=5,base=True,show=False).add_to(map)

HeatMap(heatMapDataQMstat,name='Heat Map von QM stat. Radius 10 Größe 5',radius=10,blur=5,base=True
       # ,show=False
       ).add_to(map)



shpLeitungen[~pd.isnull(shpLeitungen['geometry'])].sort_values(by=['DN'],ascending=True).explore(column='DN'
        ,cmap='cool_r',vmin=shpLeitungen['DN'].quantile(.20),vmax=shpLeitungen['DN'].quantile(.80)
       #,legend=False
        ,style_kwds={"style_function":lambda x: {"weight":min(max(x["properties"]["DN"]*facWidthinPixelDN,minWidthinPixel),maxWidthinPixel)}}
       #,tiles='CartoDB Positron' #'OpenStreetMap'
        ,name='shpLeitungen'
        ,m=map
)

gdfUe1[['MITGLIEDSN','MIS_UGSTID','MIS_BEHAEL','geometry']].explode().sort_values(by=['MIS_BEHAEL'],ascending=False).explore(column='MIS_BEHAEL'
      ,cmap='autumn_r',vmin=gdfUe1["MIS_BEHAEL"].quantile(.025),vmax=gdfUe1["MIS_BEHAEL"].quantile(.975)
     ,legend=False
      ,style_kwds={"style_function":lambda x: {"radius":min(max(x["properties"]["MIS_BEHAEL"]*facRadius,minRadius),maxRadius)}}
     #,tiles='CartoDB Positron' #'OpenStreetMap'
      ,name='shpUebergabestellen'
      ,m=map
      ,show=False
)


gdf_KNOTUe[['NAME','UGSTID','MITGLIEDSN','MIS_UGSTNA','Abstand Shp Zu Sir3s','QM stat.','geometry']].sort_values(by=['QM stat.'],ascending=True).explore(column='QM stat.'
      ,cmap='autumn_r',vmin=gdf_KNOTUe["QM stat."].quantile(.075),vmax=gdf_KNOTUe["QM stat."].quantile(.975)
     #,legend=False
      ,style_kwds={"style_function":lambda x: {"radius":min(max(x["properties"]["QM stat."]*facRadius*max((fmin,fmax)),minRadius),maxRadius)}}
     #,tiles='CartoDB Positron' #'OpenStreetMap'
      ,name='QM stat.'
      ,m=map
)
dummy=folium.LayerControl().add_to(map)

=== Kartenbeispiel Forts.

[90]:
map
[90]:
Make this Notebook Trusted to load map: File -> Trust Notebook

Bsp. Tabellenreport

[91]:
df=gdf_KNOTUe.groupby(by='MITGLIEDSN').agg({'QM stat.':[
    #'count',
    'sum']}).reset_index()
df.columns=df.columns.droplevel(1)
df=df.sort_values(by='QM stat.',ascending=False).reset_index(drop=True)
df
[91]:
MITGLIEDSN QM stat.
0 Netze BW Wasser GmbH 1568.999996
1 Sindelfingen 300.000000
2 Reutlingen, FairEnergie GmbH 296.000000
3 Heilbronn 254.999992
4 ZV Filderwasserversorgung 249.370008
... ... ...
178 Balgheim 1.000000
179 Bad Mergentheim, Stadtwerk Tauberfranken GmbH 1.000000
180 Abfallverwertungsgesellschaft Ldkr. Ludwigsburg 1.000000
181 Keilbach 0.000000
182 Telekom (De Te Immobilien) 0.000000

183 rows × 2 columns

[92]:
df['QM stat.'].describe()
[92]:
count     183.000000
mean       40.848579
std       125.997631
min         0.000000
25%         6.500000
50%        14.000000
75%        31.000000
max      1568.999996
Name: QM stat., dtype: float64
[93]:
df['QM stat.'].quantile(.33)
[93]:
8.060000000000002
[94]:
df['MITGLIEDSN']=df.apply(lambda row: row['MITGLIEDSN'] if row['QM stat.'] > df['QM stat.'].quantile(.33) else 'Rest' ,axis=1)
[95]:
df
[95]:
MITGLIEDSN QM stat.
0 Netze BW Wasser GmbH 1568.999996
1 Sindelfingen 300.000000
2 Reutlingen, FairEnergie GmbH 296.000000
3 Heilbronn 254.999992
4 ZV Filderwasserversorgung 249.370008
... ... ...
178 Rest 1.000000
179 Rest 1.000000
180 Rest 1.000000
181 Rest 0.000000
182 Rest 0.000000

183 rows × 2 columns

[96]:
df=df.groupby(by='MITGLIEDSN').agg({'QM stat.':[
    #'count',
    'sum']}).reset_index()
df.columns=df.columns.droplevel(1)
df=df.sort_values(by='QM stat.',ascending=False).reset_index(drop=True)
df
[96]:
MITGLIEDSN QM stat.
0 Netze BW Wasser GmbH 1568.999996
1 Sindelfingen 300.000000
2 Reutlingen, FairEnergie GmbH 296.000000
3 Rest 268.149999
4 Heilbronn 254.999992
... ... ...
118 Knittlingen 9.000000
119 Schefflenz 9.000000
120 Weissach 9.000000
121 Wasserversorgungsverband Jusigruppe 9.000000
122 Mössingen 9.000000

123 rows × 2 columns

[97]:
def highlight_max(s, props=''):
    return np.where(s == np.nanmax(s.values), props, '')
[98]:
dfExp=df.style.format({\
    'QM stat.':'{:5.0f}',\
})\
.background_gradient(cmap='Blues')\
.apply(highlight_max, props='color:white;background-color:pink;',subset=['QM stat.'], axis=0)\
.hide(axis='index')
dfExp
[98]:
MITGLIEDSN QM stat.
Netze BW Wasser GmbH 1569
Sindelfingen 300
Reutlingen, FairEnergie GmbH 296
Rest 268
Heilbronn 255
ZV Filderwasserversorgung 249
Ludwigsburg-Kornwestheim, Stadtwerke GmbH 247
Pforzheim, Stadtwerke GmbH & Co. KG 226
ZV Landeswasserversorgung 225
Tübingen, Stadtwerke GmbH 203
ZV WV Nordostwürttemberg 195
Villingen-Schwenningen, Stadtwerke GmbH 180
Leonberg 120
Böblingen 106
ZV Ammertal-Schönbuchgruppe 103
Esslingen a.N., Stadtwerke GmbH & Co. KG 80
Bietigheim-Bissingen, Stadtwerke GmbH 79
Albstadt, Albstadtwerke GmbH 75
Nürtingen, Stadtwerke GmbH 74
ZV Gäuwasserversorgung 70
Gerlingen 70
Mühlacker, Stadtwerke GmbH 67
Bretten, Stadtwerke GmbH 65
Rottweil 62
Tuttlingen, Stadtwerke GmbH 60
Sinsheim 56
Neckarsulm 55
Fellbach, Stadtwerke GmbH 55
ZV Baarwasserversorgung 54
ZV Wasserversorgung Zollernalb 50
Herrenberg 50
Buchen, Stadtwerke GmbH & Co. KG 48
ZV Wasserversorgungsgruppe Mühlbach 45
Vaihingen/Enz 42
ZV Renninger Wasserversorgungsgruppe 41
Mosbach, Stadtwerke GmbH 40
Metzingen 40
Weil der Stadt 40
Ditzingen 40
Markgröningen 40
Möglingen 39
ZV Steinlachwasserversorgung 35
Eningen unter Achalm 34
Bad Friedrichshall 34
Walldürn, Stadtwerke GmbH 32
ZV Besigheimer Wasserversorgungsgruppe 32
ZV Schozachwasserversorgungsgruppe 31
Schwieberdingen 31
Stockach 30
ZV Wiesaz-Wasserversorgungsgruppe 30
Weinsberg, Stadtwerke GmbH 30
ZV Strohgäu-Wasserversorgung 30
Lauffen a.N., Stadtwerke GmbH 30
Oberderdingen 26
Hechingen 25
Tamm 25
ZV Schwarzwaldwasserversorgung 25
St. Georgen 25
ZV Wasserversorgung Hohenzollern 25
Neckarwestheim 24
Ispringen 24
Magstadt 24
Pfullingen 23
Freiberg a.N. 22
Niefern-Öschelbronn 22
Kraichtal 21
Kieselbronn 20
ZV Wasserversorgungsgruppe Oberes Elsenztal 20
Brackenheim 20
ZV Wasserversorgungsgruppe Unterer Schwarzbach 20
Bad Wimpfen 20
ZV Wasserversorgung Oberer Neckar 20
ZV Wasserversorgung Hohenberggruppe 20
Uhldingen-Mühlhofen 20
Asperg 20
ZV Härdtenwasserversorgungsgruppe 19
Schwaigern 19
ZV Gruppenwasserversorgung Unteres Elsenztal 18
Gärtringen 18
Maulbronn 17
Talheim 17
Ehningen 17
Sersheim 17
ZV Buchenwasserversorgung 17
Remseck a.N. 17
Besigheim 17
Bodman-Ludwigshafen 16
Königsbach-Stein 15
Bodelshausen 15
Flein 15
ZV Wasserversorgung der Gebietsgemeinden 14
Riederich 14
Bisingen 14
Neulingen 14
Aldingen 13
Wiernsheim 13
Benningen a.N. 13
Sachsenheim 13
Erlenbach 12
Leingarten 12
Waiblingen, Stadtwerke GmbH 12
Nufringen 12
Boxberg 12
Pliezhausen 12
Burladingen 12
Illingen 11
Neuenstadt am Kocher 11
Möckmühl 11
Kusterdingen 11
Ilsfeld 11
Heimsheim 11
Triberg 10
Kirchheim a. N. 10
Ingersheim 10
Güglingen 10
Dielheim 10
Bempflingen 10
Adelsheim 10
Knittlingen 9
Schefflenz 9
Weissach 9
Wasserversorgungsverband Jusigruppe 9
Mössingen 9
[99]:
dfExp.to_excel('BspTabellenexport.xlsx',index=False)
[ ]: